package com.eec.spring.ioc;

import com.eec.spring.ioc.annotation.Component;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @author LeeC
 * @description
 * @date 2025/8/16
 * @PACKAGE_NAME com.eec.spring.ioc
 */
/**
 * 基于ConcurrentHashMap的单例工厂，实现IOC容器管理单例对象
 */
public class IOCContainer {
    // 单例IOC容器，存储单例对象：key为类名，value为单例实例
    private static final ConcurrentHashMap<String, Object> IOC = new ConcurrentHashMap<>();

    /**
     * 获取指定类的单例实例
     * @param clazz 目标类的Class对象
     * @return 单例实例
     */
    public static Object getSingleBean(Class<?> clazz) {
        if (clazz == null) {
            throw new IllegalArgumentException("类对象不能为null");
        }
        String BeanName = clazz.getName();
        if (clazz.isAnnotationPresent(Component.class)){
            String value = clazz.getAnnotation(Component.class).value();
            if (!"".equals( value)){
                BeanName = value;
            }
        }


        // 1. 先从IOC容器中获取实例
        Object instance = IOC.get(BeanName);

        // 2. 如果容器中没有，则创建实例并放入容器（双重检查锁确保线程安全）

        if (instance == null) {
            // 加锁防止多线程同时创建实例
            synchronized (IOCContainer.class) {
                // 再次检查，避免已被其他线程创建
                instance = IOC.get(BeanName);
                if (instance == null) {
                    try {
                        // 通过反射创建实例（假设类有默认无参构造方法）
                        instance = clazz.getDeclaredConstructor().newInstance();
                        // 将新创建的实例放入IOC容器
                        IOC.put(BeanName, instance);
                    } catch (Exception e) {
                        throw new RuntimeException("创建单例实例失败：" + clazz.getName(), e);
                    }
                }
            }
        }

        return instance;
    }

    public static void createBean(Class<?> clazz){
        IOCContainer.getSingleBean(clazz);
    }
    /**
     * 检查容器中是否存在指定类的单例实例
     * @param clazz 目标类的Class对象
     * @return 是否存在
     */
    public static <T> boolean containsInstance(Class<T> clazz) {
        return clazz != null && IOC.containsKey(clazz.getName());
    }
}
